from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from functools import wraps
import hashlib
import json
import logging

logger = logging.getLogger(__name__)

def cache_key_generator(*args, **kwargs):
    """生成缓存键"""
    key_data = {
        'args': args,
        'kwargs': kwargs
    }
    key_string = json.dumps(key_data, sort_keys=True)
    return hashlib.md5(key_string.encode()).hexdigest()

def cache_result(timeout=300, key_prefix=''):
    """缓存装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存键
            cache_key = f"{key_prefix}:{func.__name__}:{cache_key_generator(*args, **kwargs)}"
            
            # 尝试从缓存获取
            result = cache.get(cache_key)
            if result is not None:
                logger.debug(f"Cache hit for key: {cache_key}")
                return result
            
            # 执行函数并缓存结果
            result = func(*args, **kwargs)
            cache.set(cache_key, result, timeout)
            logger.debug(f"Cache set for key: {cache_key}")
            
            return result
        return wrapper
    return decorator

class SurveyCacheManager:
    """勘查记录缓存管理器"""
    
    CACHE_TIMEOUT = 300  # 5分钟
    
    @classmethod
    def get_user_surveys_cache_key(cls, user_id, page=1, search_params=None):
        """获取用户勘查记录列表缓存键"""
        search_hash = ''
        if search_params:
            search_hash = hashlib.md5(
                json.dumps(search_params, sort_keys=True).encode()
            ).hexdigest()[:8]
        return f"user_surveys:{user_id}:page_{page}:{search_hash}"
    
    @classmethod
    def get_survey_detail_cache_key(cls, survey_id):
        """获取勘查记录详情缓存键"""
        return f"survey_detail:{survey_id}"
    
    @classmethod
    def get_user_stats_cache_key(cls, user_id):
        """获取用户统计数据缓存键"""
        return f"user_stats:{user_id}"
    
    @classmethod
    def invalidate_user_caches(cls, user_id):
        """清除用户相关的所有缓存"""
        patterns = [
            f"user_surveys:{user_id}:*",
            f"user_stats:{user_id}",
        ]
        
        for pattern in patterns:
            try:
                keys = cache.keys(pattern)
                if keys:
                    cache.delete_many(keys)
                    logger.info(f"Invalidated cache pattern: {pattern}, keys: {len(keys)}")
            except Exception as e:
                logger.error(f"Failed to invalidate cache pattern {pattern}: {e}")
    
    @classmethod
    def invalidate_survey_cache(cls, survey_id, user_id=None):
        """清除单个勘查记录相关缓存"""
        keys_to_delete = [
            cls.get_survey_detail_cache_key(survey_id)
        ]
        
        if user_id:
            # 清除该用户的列表缓存
            pattern = f"user_surveys:{user_id}:*"
            try:
                list_keys = cache.keys(pattern)
                keys_to_delete.extend(list_keys)
                
                # 清除用户统计缓存
                keys_to_delete.append(cls.get_user_stats_cache_key(user_id))
            except Exception as e:
                logger.error(f"Failed to get cache keys for pattern {pattern}: {e}")
        
        if keys_to_delete:
            cache.delete_many(keys_to_delete)
            logger.info(f"Invalidated survey cache, keys: {len(keys_to_delete)}")

class FavoriteCacheManager:
    """常用地点缓存管理器"""
    
    CACHE_TIMEOUT = 600  # 10分钟
    
    @classmethod
    def get_user_favorites_cache_key(cls, user_id):
        """获取用户常用地点缓存键"""
        return f"user_favorites:{user_id}"
    
    @classmethod
    def invalidate_user_favorites(cls, user_id):
        """清除用户常用地点缓存"""
        cache_key = cls.get_user_favorites_cache_key(user_id)
        cache.delete(cache_key)
        logger.info(f"Invalidated favorites cache for user: {user_id}")

# 性能优化的查询集方法
class OptimizedQueryMixin:
    """优化查询的Mixin类"""
    
    def get_optimized_queryset(self):
        """获取优化的查询集"""
        if hasattr(self, 'select_related_fields'):
            queryset = self.get_queryset().select_related(*self.select_related_fields)
        else:
            queryset = self.get_queryset()
        
        if hasattr(self, 'prefetch_related_fields'):
            queryset = queryset.prefetch_related(*self.prefetch_related_fields)
        
        return queryset

# 缓存装饰器示例
@cache_result(timeout=300, key_prefix='survey_stats')
def get_cached_survey_stats(user_id):
    """获取缓存的用户统计数据"""
    from .models import SurveyRecord
    from django.utils import timezone
    from datetime import timedelta
    
    queryset = SurveyRecord.objects.filter(user_id=user_id)
    now = timezone.now()
    
    # 统计数据
    total_count = queryset.count()
    
    # 本月记录数
    month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    month_count = queryset.filter(survey_date__gte=month_start).count()
    
    # 本周记录数
    days_since_monday = now.weekday()
    week_start = (now - timedelta(days=days_since_monday)).replace(hour=0, minute=0, second=0, microsecond=0)
    week_count = queryset.filter(survey_date__gte=week_start).count()
    
    return {
        'total_surveys': total_count,
        'surveys_this_month': month_count,
        'surveys_this_week': week_count,
        'updated_at': now.isoformat()
    }

# 信号处理器 - 自动清除缓存
@receiver(post_save, sender='survey.SurveyRecord')
def invalidate_survey_cache_on_save(sender, instance, created, **kwargs):
    """勘查记录保存时清除相关缓存"""
    SurveyCacheManager.invalidate_survey_cache(
        instance.id, 
        instance.user_id
    )

@receiver(post_delete, sender='survey.SurveyRecord')
def invalidate_survey_cache_on_delete(sender, instance, **kwargs):
    """勘查记录删除时清除相关缓存"""
    SurveyCacheManager.invalidate_survey_cache(
        instance.id, 
        instance.user_id
    )

@receiver(post_save, sender='survey.FavoriteLocation')
def invalidate_favorite_cache_on_save(sender, instance, created, **kwargs):
    """常用地点保存时清除相关缓存"""
    FavoriteCacheManager.invalidate_user_favorites(instance.user_id)

@receiver(post_delete, sender='survey.FavoriteLocation')
def invalidate_favorite_cache_on_delete(sender, instance, **kwargs):
    """常用地点删除时清除相关缓存"""
    FavoriteCacheManager.invalidate_user_favorites(instance.user_id)